package collector;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @author brianegge
 * @license http://www.freebsd.org/copyright/license.html  BSD License (4 Clause)
 */
public class StatementGroup {
    private final StatementGrouping type;

    //map normalized string -> statement
    private final HashMap<String, ArrayList<Statement>> statements = new HashMap<String, ArrayList<Statement>>();
    private final AtomicLong numOfStatement = new AtomicLong(0);

    public StatementGroup(StatementGrouping type) {
        this.type = type;
    }

    /**
     * thread safe insertion
     *
     * @param s statement
     */
    public void insertStatement(Statement s) {
        String identity = s.getDumpedAST();
        numOfStatement.getAndIncrement();

        synchronized (statements) {
            if (statements.containsKey(identity)) {
                statements.get(identity).add(s);
            } else {
                ArrayList<Statement> list = new ArrayList<Statement>();
                list.add(s);
                statements.put(identity, list);
            }
        }
    }

    public void runCompare(Collector collector) {
        //compare one statement with the others in the same bucket

        for (ArrayList<Statement> statement : statements.values()) {
            compareEachStatInArray(collector, statement);
        }
    }

    public void compareEachStatInArray(Collector collector, ArrayList<Statement> statArray) {
        //get the item from 0 to N-1
        int N = statArray.size();
        for (int i = 0; i < N - 1; i++) {
            Statement s1 = statArray.get(i);
            for (int j = i + 1; j < N; j++) {
                Statement s2 = statArray.get(j);
                //Match or not
                if (s1.equals(s2)) {
                    //insert the result to matrix
                    putAMarkOnMatrix(collector, s1, s2);
                }
            }
        }
    }

    public void putAMarkOnMatrix(Collector collector, Statement s1, Statement s2) {
        //for diagonal matrix, the column number > the row number
        //get fileID and statement id of each statement
        int index1 = collector.getIndexForStat(s1);
        int index2 = collector.getIndexForStat(s2);

        //make sure fill on the upper diagonal
        if (index1 < index2) {
            collector.setTrueToCell(index1, index2);
        } else {
            collector.setTrueToCell(index2, index1);
        }
    }

    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append(type).append(": ").append(numOfStatement);
        sb.append("\t").append(statements.size()).append("[");

        for (ArrayList<Statement> statements1 : statements.values()) {
            sb.append(statements1.size()).append(", ");
        }
        sb.append("]");
        return sb.toString().intern();
    }

}
